import React from "react";
import { findDOMNode } from "react-dom";
import { connect } from "react-redux";
import Moveable from "react-moveable";
import EditCompWrapper from "components/EditCompWrapper";
import { IEditorProps } from "store/reducers/editor"
import { nameToComponentMap } from "./config";
import { SET_CURRENT_ELEMENT, SET_CURRENT_ELEMENT_PROPS } from "store/constants";
import {componentParam} from "utils";
import "./index.scss";

interface IEditAreaProps {
    editor: IEditorProps;
    setCurrentElement: (id: string) => void;
    setCurrentComponentProps: (paylod: any) => void;
}

interface IEditAreaState {
    currentCachePos: number[];  // 缓存当前操作元素位置移动
    currentCacheSize: number[];  // 缓存当前元素宽高变化
}

class EditArea extends React.Component<IEditAreaProps, IEditAreaState> {
    frame = {
        translate: [0, 0],
    };
    state: IEditAreaState = {
        currentCachePos: [0, 0],
        currentCacheSize: [0, 0]
    }

    currentRef = React.createRef();
    setCurrentElement = (id: string) => {
        const { setCurrentElement, editor } = this.props;
        const comp = editor.components.find(item => item.id === id);
        if(comp){
            const { top = 0, left = 0, width = 0, height = 0 } = comp.props;
            this.setState({currentCachePos: [top, left], currentCacheSize: [width, height]});
        }
        setCurrentElement(id);
    }
    
    setCurrentElementPosition = () => {
        const { setCurrentComponentProps } = this.props;
        const { currentCachePos } = this.state;
        setCurrentComponentProps({
            top: `${currentCachePos?.[0]}px`,
            left: `${currentCachePos?.[1]}px`
        })
    }

    setCurrentElementSize = () => {
        const { setCurrentComponentProps } = this.props;
        const { currentCacheSize } = this.state;
        setCurrentComponentProps({
            width: `${currentCacheSize?.[0]}px`,
            height: `${currentCacheSize?.[1]}px`
        })
    }

    // 检测点击当前选中组件外部
    handleClickOutside = (e: MouseEvent) => {
        const cureentDom = document.querySelector(`.edit-area-wrapper`)
        const canClickArea = document.querySelector(`.right-props-wrapper`);
        const modalArea = document.querySelector(`.ant-modal-root`);
        if(cureentDom){
            let result = (findDOMNode(cureentDom) as any)?.contains((e.target as any));
            let canResult = (findDOMNode(canClickArea) as any)?.contains((e.target as any));
            let modalResult = (findDOMNode(modalArea) as any)?.contains((e.target as any));
            if(!result && !canResult && !modalResult){
                this.props.setCurrentElement("")
            }
        }
    }

    componentDidMount(){
        document.addEventListener("mousedown", this.handleClickOutside, false);
    }
    componentWillUnmount(){
        document.removeEventListener('mousedown', this.handleClickOutside, false);
    }

    render(){
        const { editor } = this.props;
        const { components, currentElement } = editor;
        const { currentCachePos, currentCacheSize } = this.state;
        return <div className="edit-area-wrapper" style={{...editor.defaultPageStyle}}>
            {
                components.map(item => {
                    const comp = Reflect.get(nameToComponentMap, item.name);
                    const { styleProps, componentProps } = componentParam(item.props, comp.styleKeyNames);
                    if(item.id === currentElement) {
                        styleProps.width = currentCacheSize?.[0];
                        styleProps.height = currentCacheSize?.[1];
                    }
                    const Comp = comp.Comp;
                    return Comp ? <EditCompWrapper
                        top={currentElement === item.id ? (currentCachePos?.[0] || 0) : styleProps?.top}
                        left={currentElement === item.id ? (currentCachePos?.[1] || 0) : styleProps?.left}
                        className={`edit-item-${item.id}`}
                        onClick={() => this.setCurrentElement(item.id)}
                        key={item.id}
                    >
                        <Comp {...item.props} style={styleProps} componentProps={componentProps} />
                    </EditCompWrapper> : null;
                })
            }
            <Moveable 
                target={(document.querySelector(`.edit-item-${editor.currentElement}`) as any)}
                draggable={true}
                pinchable={true}
                resizable={true}
                throttleResize={0}
                throttleDrag={0}
                onDrag={(e) => this.setState({currentCachePos: [e.top, e.left]})}
                onDragEnd={() => this.setCurrentElementPosition()}
                onResizeStart={({ target, set, setOrigin, dragStart }) => {
                    setOrigin(["%", "%"]);
                    const style = window.getComputedStyle(target);
                    const cssWidth = parseFloat(style.width);
                    const cssHeight = parseFloat(style.height);
                    set([cssWidth, cssHeight]);
                    dragStart && dragStart.set(this.frame.translate);
                }}
                onResize={(e) => {
                    const { target, drag } = e;
                    // this.setCurrentElementSize(e);
                    this.setState({currentCacheSize: [e.width, e.height]})
                    this.frame.translate = drag.beforeTranslate;
                    target.style.transform = `translate(${drag.beforeTranslate[0]}px, ${drag.beforeTranslate[1]}px)`;
                }}
                onResizeEnd={() => this.setCurrentElementSize()}
            />
        </div>
    }
}

export default connect((state: any) => {
    return { editor: state?.editor }
}, (dispatch) => {
    return {
        setCurrentElement: (id: string) => dispatch({ type: SET_CURRENT_ELEMENT, payload: id }),
        setCurrentComponentProps: (payload: any) => dispatch({type: SET_CURRENT_ELEMENT_PROPS, payload})
    }
})(EditArea);